package com.sdkx.app.datalayers;

import android.content.Context;
import android.os.Handler;
import android.os.Looper;

import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import cn.creable.gridgis.controls.MapControl;
import cn.creable.gridgis.geometry.IEnvelope;

public class LayersFactory {
    private static LayersFactory instance = new LayersFactory();
    LayersUpdateThread thread ;
    public ArrayList<MapDraw> getMapDraws() {
        return mapDraws;
    }

    ArrayList<MapDraw> mapDraws = new ArrayList<>();
    WeakReference<MapControl> mapReference = new WeakReference<>(null);
    ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
    Context appContext;
    Handler handler;
    IEnvelope iEnvelope;
    public void setMapControl(MapControl control) {
        mapReference = new WeakReference<>(control);
    }

    public void setContext(Context context) {
        appContext = context;
    }

    private LayersFactory() {
        handler = new Handler(Looper.getMainLooper());
    }

    public static LayersFactory getInstance() {
        return instance;
    }

    public void initLayers(){
        MapControl mapControl = mapReference.get();
        if(mapControl != null) {
            mapControl.addCustomDraw(getItemByClass(HelicopterPanel.class));//new HelicopterPanel(getContext(),mapControl)
            mapControl.setCustomDraw(getItemByClass(TackPointsPanel.class));
            mapControl.addCustomDraw(getItemByClass(MarkPointsPanel.class));
            mapControl.addCustomDraw(getItemByClass(AlarmAreaLayer.class));
            mapControl.addCustomDraw(getItemByClass(AirSpaceLayer.class));
            mapControl.addCustomDraw(getItemByClass(WayPointsLayer.class));
        }
    }
    public MapDraw getItemByClass(Class<? extends  MapDraw> cls) {
        MapDraw mapDraw = null;
        if (cls == null) return mapDraw;
        for (MapDraw mapcls : mapDraws) {
            if(mapcls == null) continue;
            if (mapcls.getClass().equals(cls)) {
                mapDraw = mapcls;
                break;
            }
        }
        if (mapDraw == null) {
            try {
                mapDraw = cls.getConstructor(Context.class).newInstance(appContext);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (NoSuchMethodException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
            mapDraws.add(mapDraw);
        }
        if(mapDraw != null) {
            MapControl control = mapReference.get();
            if (control != null) {
                mapDraw.setMapControl(control);
            } else {
                mapDraw = null;
            }
        }
        return mapDraw;
    }

   public  void updateSingleCustom(final Class<? extends MapDraw> cls,IUpdateLister lister){
        if(lister == null)return;
       MapDraw mapDraw =  getItemByClass(cls);
       cachedThreadPool.execute(new UpdateRunnable(mapDraw,lister));
    }
    public void update(){
        IUpdateLister lister = new IUpdateLister() {
            @Override
            public void onUpdated() {
                MapControl control = mapReference.get();
                if(control != null){
                    control.refresh();
                }
            }
        };
        for(MapDraw draw : mapDraws){
                   // draw.upData();
            cachedThreadPool.execute(new UpdateRunnable(draw,lister));
        }
//        thread.putTask(new Runnable() {
//            @Override
//            public void run() {
//                for(MapDraw draw : mapDraws){
//                    draw.upData();
//                }
//            }
//        });
    }
    public boolean isScreenChanaged(IEnvelope env){
        return isEnvChanaged(env);
    }
    private boolean isEnvChanaged(IEnvelope iEnv) {
        if(iEnvelope == null){
            iEnvelope = iEnv;
            return true;
        }
        boolean xmax = iEnvelope.getXMax() == iEnv.getXMax();
        boolean xMin = iEnvelope.getXMin() == iEnv.getXMin();
        boolean yMax = iEnvelope.getYMax() == iEnv.getYMax();
        boolean yMin = iEnvelope.getYMin() == iEnv.getYMin();
        return !(xmax && xMin && yMax && yMin);
    }
    public void setEnv(IEnvelope env){
       iEnvelope = env;
    }

    public interface IUpdateLister{
        void onUpdated();
    }

    private class UpdateRunnable implements Runnable{
        IUpdateLister iUpdateLister;
        MapDraw mapDraw;
        public UpdateRunnable(MapDraw maplayer,IUpdateLister lister){
            iUpdateLister = lister;
            mapDraw = maplayer;
        }
        @Override
        public void run() {
            if(mapDraw != null)
                mapDraw.upData();
            handler.post(new Runnable() {
                @Override
                public void run() {
                    iUpdateLister.onUpdated();
                }
            });
        }
    }
}